【JavaScript】JavaScript高级程序设计 第四章 变量 作用域和内存问题

4.1基本类型和引用类型的值

ECMAScript变量可能包含两种不同数据类型的值 基本类型值 和 引用类型

值。

基本类型值:简单的数据段

引用类型值:可能由多个值构成的对象

将一个值赋给变量时,解析器必须确定这个值是基本数据类型还是引用类型。

基本数据类型:按值访问,可以操作保存在变量中的实际的值。

引用类型的值:按引用访问
4.1.1动态的属性

对于引用类型的值可以添加、修改和删除属性和方法,不能给基本类型的值添加属性(但不会报错,undefined)

4.1.2复制变量值

复制基本类型的值:在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

复制引用类型的值:复制是一个指针,指向同一个对象。所以改变其中一个变量就会影响另一个变量。

4.1.3传递参数

ECMAScript中所有函数的参数都是按值传递:把函数外部的值复制给函数内部的参数。

传递基本类型的值:被传递的值会复制给一个局部变量(即命名参数,也就是arguments对象中的一个元素)

传递引用类型的值:把被传递的值在内存中的地址复制给一个局部变量。因此这个局部变量的变化会反映在函数的外部

提示:可以把ECMAScript函数的参数想象成局部变量

4.1.4检测类型

检查基本数据类型:typeof操作符

检测引用类型的值:instanceof操作符

4.2执行环境及作用域

执行环境:定义变量或函数有权访问的其他数据,决定了它们各自的行为。

变量对象:每个执行环境都有的一个变量对象,保存环境中定义的所有变量和函数。代码无法访问,解析器会使用。

全局执行环境:最外围的一个执行环境。在web浏览器中是window对象。

函数的执行环境:每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。

作用域链:保证对执行环境有权访问的所有变量和函数的有序访问。

作用域链的前端始终是当前环境的变量对象。(如果这个变量是函数,将它活动对象作为变量对象)(活动对象在最开始只包含arguments对象)

作用域链中下一个变量对象来自于外部环境,在下一个为下一个外部环境……

作用域链的最后一个对象始终是全局执行环境的变量对象。

标识符解析:沿这作用域链一级一级地搜索标识符的过程。从作用域链最前端开始逐级向后回溯直到找到标识符。

内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。

4.2.1延长作用域链

try-catch语句的catch块和with语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。

catch语句:创建一个新的变量对象,包含被抛出的错误对象的声明。

with语句:将指定的对象添加到作用域链中。

4.2.2没有块级作用域

js中,if语句for语句中的变量声明会将变量添加到当前的执行环境中。

声明变量

使用var声明的变量会自动被添加到最接近的环境中

没使用var声明该变量会自动被添加到全局环境中

提示:1.不声明而直接初始化变量是一个常见的错误做法,在严格模式下会报错

查询标识符

搜索过程从作用域的前端开始,向上逐级查询与给定名字匹配的标识符

如果局部环境存在同名标识符,就不会使用位于父环境中的标识符

提示:1.访问局部变量要比访问全局变量快,因为不用向上搜索作用域链。js引擎优化标识符查询使这个差别可以忽略不计。

4.3垃圾收集

执行环境负责管理代码执行过程中使用的内存

原理:找出不再使用的变量释放其占用的内存

垃圾收集器会按照固定的时间间隔周期性的执行

垃圾收集器必须跟踪哪个变量有用哪个变量没用,对不再有用的变量打上标记。

标识方式:1.标记清除 2.引用计数

4.3.1标记清除

最常用

当变量进入环境时标记为“进入环境”,离开环境时标记为“离开环境”。

垃圾收集器在运行时给内存中所有变量打上标记,然后去掉环境中的变量以及被环境中的变量引用的变量的标记。这时仍有标记的变量为准备删除的变量。最后垃圾收集器完成内存清除工作,销毁带标记的值并回收内存空间。

4.3.2引用计数

不常见

跟踪记录每个值被引用的次数。

4.3.3性能问题

垃圾收集器是周期性运行。

垃圾收集例程回收的内存分配量低于15%,则变量字面量数组元素的临界值就会加倍。

提示:有的浏览器可以出发垃圾收集过程但不推荐。

4.3.4管理内存

优化内存:不用的数据设置为null来释放引用(解除引用)。局部变量会在离开执行环境时自动被解除引用。

解除一个值的引用并不意味着自动回收该值所占的内存,而是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。